/**
 * Copyright 2010 Victor Egea Hernando
 *
 * RockScript is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 * 
 * RockScript is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with RockScript.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef VMACHINE_H_
#define VMACHINE_H_

#include "vm_misc.h"
#include "paper2lir.h"
#include "picojit/pjit_buffer.h"

namespace paper{

// declared classes
class paper2lir;

//! @brief
class PAPER_API vmachine{

public:
	// FLAGS
	enum __vm_flags{
		jit_enabled = 1 << 0, debug_enabled = 1 << 1,
		print_jit = 1 << 2, print_gc = 1 << 3, print_opcodetrace = 1 << 4
	};
    // CONSTRUCTIR & DESTRUCTOR
    vmachine( corelib::uint32 size = PWRTWO(20) );
    virtual ~vmachine();

    // HANDLER MANAGEMENT
	void set_hnd( vmachine_hnd &hnd );

    // CLASS MANAGEMENT
    corelib::pair<vm_class*, bool>add_class( const corelib::ustring &str );
    corelib::pair<vm_class*, bool>get_class( const corelib::ustring &str );
    corelib::int32 get_class_idx( const corelib::ustring &str );

    // RUN / RESET
    bool run( const corelib::ustring &c, const corelib::ustring &m );
    void reset( void );

    // GETTERS/ SETTERS
	__register &argument( corelib::uint32 index );
	__register &spreg( corelib::int32 index );
	const __register &lret( void ) const;

	// DEBUG & GC
	INLINE static void send_error( vmachine &vm, const corelib::ustring &str );
	INLINE static void disassemble( vmachine &vm, std::ostream &os );
	INLINE static void backtrace( vmachine &vm, std::ostream &os );
	INLINE static void garbage_collector( vmachine &vm, corelib::uint32 cycles );
	INLINE static void memory_stamp( vmachine &vm, std::ostream &os );

	// [JIT] complex opcodes
	INLINE static bool jit_method( vmachine &vm, method &method );
	INLINE static bool CDECL op_kccall( vmachine &vm, corelib::uint32 ci, corelib::uint32 mi, bool &jitted );
	INLINE static void CDECL op_new( vmachine &vm, corelib::int32 type, __register &reg );
	INLINE static void CDECL op_delete( vmachine &vm, __register &reg );
	INLINE static void CDECL op_return( vmachine &vm, __register &reg );
	INLINE static bool CDECL op_cppcode( vmachine &vm );

public:
	// FRIEND CLASSES
	friend class paper2lir;

protected:
    // INNER FUNCTIONS
    void add_routine( void );
    corelib::ustring unmangle_method_name( const corelib::ustring &mstr ) const;
    bool load_sfunction( const corelib::ustring &vc, const corelib::ustring &vm );

protected:
    // types
    typedef std::set<object*> __obj_set;
	typedef corelib::hash_map<const vm_class *, corelib::uint32,
		vm_class_hash, vm_class_equalkey> __class_map;

protected:
    // CLASS INDEXES
    corelib::uint32 _object_cidx, _string_cidx, _array_cidx;
    corelib::uint32 _ibuffer_cidx, _rbuffer_cidx, _bbuffer_cidx;
	// VM HANDLER & ACTIVE ROUTINE
	vmachine_hnd *_hnd;
	routine *_aroutine;
	__class_map _class_map;
	corelib::real32 _max_cycles;
	std::list<routine*> _routine;
	std::vector<vm_class*> _class;
	// [GC] OBJECT GENERATIONS & COUNTER
	corelib::uint32 _gc_count;
    __obj_set _objects0;
    __obj_set _objects1;
    __obj_set _objects2;
	// virtual machine flags
	corelib::uint32 _flags;
	// current instruction
	instruction _ci;


};

#include "vm_inline.h"

}; // namespace paper

#endif // VMACHINE_H_
